home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 129_01.zip / 210LOG.C < prev    next >
Text File  |  1993-06-01  |  18KB  |  615 lines

  1. /************************************************************************/
  2. /*                log.c                    */
  3. /*                                    */
  4. /*       userlog code for  Citadel bulletin board system        */
  5. /************************************************************************/
  6.  
  7. /************************************************************************/
  8. /*                history                 */
  9. /*                                    */
  10. /* 84Dec28 HAW    findPerson() moved from MSG.C to LOG.C.         */
  11. /* 84Dec12 HAW    Fixed kill acct. bug so killed acct doesn't become login*/
  12. /* 84Jun23 HAW&JLS  Eliminating unused local variables using CRF.    */
  13. /* 84Jun19 JLS    Fixed terminate so that Mail> doesn't screw up SYSOP.    */
  14. /* 84Apr04 HAW    Started upgrade to BDS C 1.50a.             */
  15. /* 83Feb27 CrT    Fixed login-in-Mail> bug.                */
  16. /* 83Feb26 CrT    Limited # new messages for new users.            */
  17. /* 83Feb18 CrT    Null pw problem fixed.                    */
  18. /* 82Dec06 CrT    2.00 release.                        */
  19. /* 82Nov03 CrT    Began local history file & general V1.2 cleanup     */
  20. /************************************************************************/
  21.  
  22. #include <210ctdl.h>
  23.  
  24. /************************************************************************/
  25. /*                contents                */
  26. /*                                    */
  27. /*    crypte()        encrypts/decrypts data blocks        */
  28. /*    findPerson()        load log record for named person    */
  29. /*    getLog()        loads requested userlog record        */
  30. /*    hash()            hashes a string to an integer        */
  31. /*    login()         is menu-level routine to log caller in    */
  32. /*    logInit()        builds the RAM index to userlog.buf    */
  33. /*    newPW()         is menu-level routine to change a PW    */
  34. /*    newUser()        menu-level routine to log a new caller    */
  35. /*    noteLog()        enters a userlog record into RAM index    */
  36. /*    putLog()        stores a logBuffer into citadel.log    */
  37. /*    PWSlot()        returns userlog.buf slot password is in */
  38. /*    slideLTab()        support routine for sorting logTab    */
  39. /*    sortLog()        sort userlog by time since last call    */
  40. /*    storeLog()        store data in log            */
  41. /*    strCmpU()        strcmp(), but ignoring case distinctions*/
  42. /*    terminate()        menu-level routine to exit system    */
  43. /*    zapLogFile()        erases & re-initializes userlog.buf    */
  44. /************************************************************************/
  45.  
  46. /************************************************************************/
  47. /*    crypte() encrypts/decrypts data blocks                */
  48. /*                                    */
  49. /*  This was at first using a full multiply/add pseudo-random sequence    */
  50. /*  generator, but 8080s don't like to multiply.  Slowed down I/O    */
  51. /*  noticably.    Rewrote for speed.                    */
  52. /************************************************************************/
  53. #define b    fpc1
  54. #define c    fi1
  55. #define s    fi2
  56. crypte(buf, len, seed)
  57. char      *buf;
  58. unsigned  len, seed;
  59. {
  60.     seed    = (seed + cryptSeed) & 0xFF;
  61.     b        = buf;
  62.     c        = len;
  63.     s        = seed;
  64.     for (;  c;    c--) {
  65.     *b++   ^= s;
  66.     s    = (s + CRYPTADD)  &  0xFF;
  67.     }
  68. }
  69.  
  70. /************************************************************************/
  71. /*    findPerson() loads log record for named person.         */
  72. /*    RETURNS: ERROR if not found, else log record #            */
  73. /************************************************************************/
  74. int findPerson(name, lBuf)
  75. char            *name;
  76. struct logBuffer    *lBuf;
  77. {
  78.     int  h, i, foundIt, logNo;
  79.  
  80.     h    = hash(name);
  81.     for (foundIt=i=0;  i<MAXLOGTAB && !foundIt;  i++) {
  82.     if (logTab[i].ltnmhash == h) {
  83.         getLog(lBuf, logNo = logTab[i].ltlogSlot);
  84.         if (strCmpU(name, lBuf->lbname) == SAMESTRING) {
  85.         foundIt = TRUE;
  86.         }
  87.     }
  88.     }
  89.     if (!foundIt)    return ERROR;
  90.     else         return logNo;
  91. }
  92.  
  93. /************************************************************************/
  94. /*    getLog() loads requested log record into RAM buffer        */
  95. /************************************************************************/
  96. getLog(lBuf, n)
  97. struct logBuffer    *lBuf;
  98. int            n;
  99. {
  100.     if (lBuf == &logBuf)   thisLog    = n;
  101.  
  102.     n    *= SECSPERLOG;
  103.  
  104.     seek(logfl, n, 0);
  105.     if (read(logfl, lBuf, SECSPERLOG) == -1) {
  106.     printf("?getLog-read fail");
  107.     }
  108.  
  109.     crypte(lBuf, (SECSPERLOG*SECTSIZE), n);    /* decode buffer    */
  110. }
  111.  
  112. /************************************************************************/
  113. /*    hash() hashes a string to an integer                */
  114. /************************************************************************/
  115. int hash(str)
  116. char *str;
  117. {
  118.     char toUpper();
  119.     int  h, i, shift;
  120.  
  121.     for (h=shift=0;  *str;  shift=(shift+1)&7, str++) {
  122.     h ^= (i=toUpper(*str)) << shift;
  123.     }
  124.     return h;
  125. }
  126.  
  127. /************************************************************************/
  128. /*    login() is the menu-level routine to log someone in        */
  129. /************************************************************************/
  130. login(password)
  131. char *password;    /* TRUE if parameters follow    */
  132. {
  133.     char getYesNo();
  134.     int  foundIt, ltentry;
  135.  
  136.     foundIt =     ((ltentry = PWSlot(password, /* load == */ TRUE)) != ERROR);
  137.  
  138.     if (foundIt && *password) {
  139.  
  140.     /* recite caller's name, etc:     */
  141.     mPrintf(" %s\n", logBuf.lbname);
  142.  
  143.     /* update userlog entries: */
  144.  
  145.     loggedIn     = TRUE;
  146.     setUp(TRUE);
  147.  
  148.     showMessages(NEWoNLY, FALSE);
  149.  
  150.     listRooms(/* doDull== */ !expert);
  151.  
  152.     outFlag = OUTOK;
  153.     if (
  154.         (
  155.         logBuf.lbId[MAILSLOTS-1]
  156.         -
  157.         (logBuf.lbvisit[   logBuf.lbgen[MAILROOM] & CALLMASK   ]+1)
  158.         < 0x8000
  159.         )
  160.         &&
  161.         logBuf.lbId[MAILSLOTS-1] - oldestLo       < 0x8000
  162.         &&
  163.         thisRoom != MAILROOM
  164.     )   {
  165.         mPrintf("\n  * You have private mail in Mail> *\n ");
  166.     }
  167.  
  168.     } else {
  169.     /* discourage password-guessing: */
  170.     if (strLen(password) > 1 && whichIO == MODEM)    pause(2000);
  171.     if (!unlogLoginOk  &&  whichIO == MODEM)  {
  172.         mPrintf(" No record -- leave message to 'sysop' in Mail>\n ");
  173.     } else if (getYesNo(" No record: Enter as new user"))    newUser();
  174.     }
  175. }
  176.  
  177. /************************************************************************/
  178. /*    logInit() indexes userlog.buf                    */
  179. /************************************************************************/
  180. logInit()
  181. {
  182.     int i;
  183.     int count;
  184.  
  185.     count = 0;
  186.  
  187.     /* clear logTab */
  188.     for (i=0;  i<MAXLOGTAB;  i++) logTab[i].ltnewest    = ERROR;
  189.  
  190.     /* load logTab: */
  191.     for (thisLog=0;  thisLog<MAXLOGTAB;  thisLog++) {
  192.     printf("log#%d", thisLog);
  193.     getLog(&logBuf, thisLog);
  194.  
  195.     /* count valid entries:         */
  196.     if (logBuf.lbvisit[0] != ERROR) {
  197.         count++;
  198.         printf("  %s", logBuf.lbname);
  199.     }
  200.     putChar('\n');
  201.  
  202.     /* copy relevant info into index:   */
  203.     logTab[thisLog].ltnewest = logBuf.lbvisit[0];
  204.     logTab[thisLog].ltlogSlot= thisLog;
  205.     logTab[thisLog].ltnmhash = hash(logBuf.lbname);
  206.     logTab[thisLog].ltpwhash = hash(logBuf.lbpw  );
  207.     }
  208.     printf(" logInit--%d valid log entries\n", count);
  209.     sortLog();
  210. }
  211.  
  212. /************************************************************************/
  213. /*    newPW() is menu-level routine to change one's password        */
  214. /*    since some Citadel nodes run in public locations, we avoid    */
  215. /*    displaying passwords on the console.                */
  216. /************************************************************************/
  217. newPW()
  218. {
  219.     char oldPw[NAMESIZE];
  220.     char pw[NAMESIZE];
  221.     char *s;
  222.     int  goodPW;
  223.  
  224.     /* save password so we can find current user again: */
  225.     if (!loggedIn) {
  226.     mPrintf("?Can't change pwd when not logged in!\n ");
  227.     return ;
  228.     }
  229.     strcpy(oldPw, logBuf.lbpw);
  230.     storeLog();
  231.     do {
  232.     echo    = CALLER;
  233.     getNormStr(" new password", pw, NAMESIZE);
  234.     echo    = BOTH;
  235.  
  236.     /* check that PW isn't already claimed: */
  237.     goodPW = (PWSlot(pw, /* load == */ TRUE) == ERROR  &&  strlen(pw) >= 2);
  238.  
  239.     if (!goodPW) mPrintf("\n Poor password\n ");
  240.  
  241.     } while (!goodPW && (haveCarrier || whichIO==CONSOLE));
  242.  
  243.     doCR();
  244.     PWSlot(oldPw, /* load == */TRUE);    /* reload old log entry         */
  245.     pw[NAMESIZE-1] = 0x00;        /* insure against loss of carrier:  */
  246.  
  247.     if (goodPW    &&  strlen(pw) > 1) {    /* accept new PW:            */
  248.     strcpy(logBuf.lbpw, pw);
  249.     logTab[0].ltpwhash    = hash(pw);
  250.     }
  251.  
  252.     mPrintf("\n %s\n pw: ", logBuf.lbname);
  253.     echo = CALLER;
  254.     mPrintf("%s\n ", logBuf.lbpw);
  255.     echo = BOTH;
  256. }
  257.  
  258. /************************************************************************/
  259. /*    newUser() prompts for name and password             */
  260. /************************************************************************/
  261. newUser() {
  262.     char    getYesNo();
  263.     char    fullnm[NAMESIZE];
  264.     char    pw[NAMESIZE];
  265.     int     good, g, h, i, ok, ourSlot;
  266.     unsigned    low;
  267.  
  268.  
  269.     configure();    /* make sure new users configure reasonably    */
  270.  
  271.     if (!expert)   tutorial("password.blb");
  272.  
  273.     do {
  274.     /* get name and check for uniqueness... */
  275.     do {
  276.         getNormStr(" Name", fullnm, NAMESIZE);
  277.         h     = hash(fullnm);
  278.         for (i=0, good=TRUE;   i<MAXLOGTAB && good;   i++) {
  279.         if (h == logTab[i].ltnmhash) good = FALSE;
  280.         }
  281.         if (
  282.         !h
  283.         ||
  284.         h==hash("Citadel")
  285.         ||
  286.         h==hash("Sysop")
  287.         ) {
  288.         good = FALSE;
  289.         }
  290.         /* lie sometimes -- hash collision !=> name collision */
  291.         if (!good) mPrintf("We already have a %s\n", fullnm);
  292.     } while (!good    &&  (haveCarrier || whichIO==CONSOLE));
  293.  
  294.     /* get password and check for uniqueness...    */
  295.     do {
  296.         echo    = CALLER;
  297.         getNormStr(" password",  pw, NAMESIZE);
  298.         echo    = BOTH    ;
  299.  
  300.         h     = hash(pw);
  301.         for (i=0, good=strLen(pw) > 1;  i<MAXLOGTAB  &&  good;  i++) {
  302.         if (h == logTab[i].ltpwhash) good = FALSE;
  303.         }
  304.         if (!h)   good = FALSE;
  305.         if (!good) {
  306.         mPrintf("\n Poor password\n ");
  307.         }
  308.     } while( !good    &&  (haveCarrier || whichIO==CONSOLE));
  309.  
  310.     mPrintf("\n nm: %s", fullnm);
  311.     mPrintf("\n pw: ");
  312.     echo = CALLER;
  313.     mPrintf("%s\n ", pw);
  314.     echo = BOTH;
  315.     } while (
  316.     !getYesNo("OK")
  317.     &&
  318.     (haveCarrier || whichIO==CONSOLE)
  319.     );
  320.  
  321.     if (ok && (haveCarrier || whichIO==CONSOLE)) {
  322.  
  323.     /* kick least recent caller out of userlog and claim entry:    */
  324.     ourSlot         = logTab[MAXLOGTAB-1].ltlogSlot;
  325.     slideLTab(0, MAXLOGTAB-1);
  326.     logTab[0].ltlogSlot = ourSlot;
  327.     getLog(&logBuf, ourSlot);
  328.  
  329.     /* copy info into record:    */
  330.     strcpy(logBuf.lbname, fullnm);
  331.     strcpy(logBuf.lbpw, pw);
  332.  
  333.     low = newestLo-50;
  334.     if (oldestLo-low < 0x8000)   low = oldestLo;
  335.     for (i=1;  i<MAXVISIT;    i++)   logBuf.lbvisit[i]= low;
  336.     logBuf.lbvisit[                   0]= newestLo;
  337.     logBuf.lbvisit[            (MAXVISIT-1)]= oldestLo;
  338.  
  339.     /* initialize rest of record:    */
  340.     for (i=0;  i<MAXROOMS;    i++) {
  341.         if (roomTab[i].rtflags & PUBLIC) {
  342.         g = (roomTab[i].rtgen);
  343.         logBuf.lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
  344.         } else {
  345.         /* set to one less */
  346.         g = (roomTab[i].rtgen + (MAXGEN-1)) % MAXGEN;
  347.         logBuf.lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
  348.         }
  349.     }
  350.     for (i=0;  i<MAILSLOTS;  i++)  {
  351.         logBuf.lbslot[i]    = 0;
  352.         logBuf.lbId[  i]    = oldestLo -1;
  353.     }
  354.  
  355.     /* fill in logTab entries    */
  356.     logTab[0].ltpwhash    = hash(pw)       ;
  357.     logTab[0].ltnmhash    = hash(fullnm)       ;
  358.     logTab[0].ltlogSlot    = thisLog       ;
  359.     logTab[0].ltnewest    = logBuf.lbvisit[0];
  360.  
  361.     /* special kludge for Mail> room, to signal no new mail:   */
  362.     roomTab[MAILROOM].rtlastMessage = logBuf.lbId[MAILSLOTS-1];
  363.  
  364.     loggedIn = TRUE;
  365.  
  366.     storeLog();
  367.  
  368.     listRooms(/* doDull== */ !expert);
  369.     }
  370. }
  371.  
  372. /************************************************************************/
  373. /*    noteLog() notes logTab entry in RAM buffer in master index    */
  374. /************************************************************************/
  375. noteLog()
  376. {
  377.     int i, slot;
  378.  
  379.     /* figure out who it belongs between:    */
  380.     for (i=0;  logTab[i].ltnewest > logBuf.lbvisit[0];    i++);
  381.  
  382.     /* note location and open it up:        */
  383.     slot = i;
  384.     slideltab(slot, MAXLOGTAB-1);
  385.  
  386.     /* insert new record */
  387.     logTab[slot].ltnewest    = logBuf.lbvisit[0]  ;
  388.     logTab[slot].ltlogSlot    = thisLog         ;
  389.     logTab[slot].ltpwhash    = hash(logBuf.lbpw)  ;
  390.     logTab[slot].ltnmhash    = hash(logBuf.lbname);
  391. }
  392.  
  393. /************************************************************************/
  394. /*    putLog() stores givend log record into ctdllog.sys        */
  395. /************************************************************************/
  396. putLog(lBuf, n)
  397. struct logBuffer    *lBuf;
  398. int            n;
  399. {
  400.     n    *= SECSPERLOG;
  401.  
  402.     crypte(lBuf, (SECSPERLOG*SECTSIZE), n);    /* encode buffer    */
  403.  
  404.     seek(logfl, n, 0);
  405.     if (write(logfl, lBuf, SECSPERLOG) != SECSPERLOG) {
  406.     printf("?putLog-write fail");
  407.     }
  408.  
  409.     crypte(lBuf, (SECSPERLOG*SECTSIZE), n);    /* decode buffer    */
  410. }
  411.  
  412. /************************************************************************/
  413. /*    PWSlot() returns userlog.buf slot password is in, else ERROR    */
  414. /*    NB: we also leave the record for the user in logBuf, if asked.    */
  415. /************************************************************************/
  416. int PWSlot(pw, load)
  417. char pw[NAMESIZE];
  418. char load;
  419. {
  420.     int          h, i;
  421.     int          foundIt, ourSlot;
  422.     struct logBuffer lbuf;
  423.  
  424.     if (strLen(pw) == 0) return ERROR;        /* Yes, this is needed. */
  425.     h = hash(pw);
  426.  
  427.     /* Check all passwords in memory: */
  428.     for(i = 0, foundIt = FALSE;  !foundIt && i < MAXLOGTAB;  i++) {
  429.     /* check for password match here */
  430.  
  431.     /* If password matches, check full password            */
  432.     /* with current newUser code, password hash collisions should    */
  433.     /* not be possible... but this is upward compatible & cheap    */
  434.     if (logTab[i].ltpwhash == h) {
  435.         ourSlot    = logTab[i].ltlogSlot;
  436.         getLog(&lbuf, ourSlot);
  437.  
  438.         if (strCmpU(pw, lbuf.lbpw) == SAMESTRING) {
  439.         /* found a complete match */
  440.         thisSlot = i   ;
  441.         foundIt  = TRUE;
  442.         }
  443.     }
  444.     }
  445.     if (foundIt) {
  446.     if (load == TRUE) {
  447.         movmem(&lbuf, &logBuf, sizeof logBuf);
  448.         thisLog = ourSlot;
  449.     }
  450.     return thisSlot;
  451.     }
  452.     else
  453.     return ERROR   ;
  454. }
  455.  
  456. /************************************************************************/
  457. /*    slideLTab() slides bottom N lots in logTab down.  For sorting.    */
  458. /************************************************************************/
  459. slideLTab(slot, last)
  460. int slot;
  461. int last;
  462. {
  463.     int i;
  464.  
  465.     /* open slot up: (movmem isn't guaranteed on overlaps) */
  466.     for (i=last-1;  i>=slot;  i--)  {
  467.     movmem(&logTab[i], &logTab[i+1], sizeLTentry);
  468.     }
  469. }
  470.  
  471. /************************************************************************/
  472. /* sortLog ShellSorts userlog by time of last call            */
  473. /************************************************************************/
  474. sortLog()
  475. {
  476. #define TSIZE 10
  477.     char *temp[TSIZE];
  478.     int finis, i, intCount, step;
  479.  
  480.     printf("sortLog...\n");
  481.     if(sizeLTentry > TSIZE) {
  482.     printf("!!!increase TSIZE in sortLog to %>d\n", sizeLTentry);
  483.     }
  484.  
  485.     intCount = 0;
  486.     for(finis=FALSE, step=MAXLOGTAB >> 1;  !finis || step>1;  ) {
  487.     if (finis) {
  488.         step = step/3 + 1;
  489.         finis = FALSE;
  490.     }
  491.  
  492.     finis    = TRUE;
  493.  
  494.     printf("stepsize=%d\n", step);
  495.  
  496.     for(i=step;  i<MAXLOGTAB;  i++) {
  497.         if(logTab[i-step].ltnewest < logTab[i].ltnewest) {
  498.         intCount++;
  499.         finis    = FALSE;
  500.  
  501.         /* interchange two entries */
  502.         movmem(&logTab[i-step], temp, sizeLTentry);
  503.         movmem(&logTab[i], &logTab[i-step], sizeLTentry);
  504.         movmem(temp, &logTab[i], sizeLTentry);
  505.         }
  506.     }
  507.     }
  508.     printf("sortLog: %d interchanges\n", intCount);
  509. }
  510.  
  511. /************************************************************************/
  512. /*    storeLog() stores the current log record.            */
  513. /************************************************************************/
  514. storeLog()  {
  515.  
  516.     logTab[0].ltnewest        = newestLo;
  517.  
  518.     logBuf.lbvisit[0]        = newestLo;
  519.     logBuf.lbwidth        = termWidth;
  520.     logBuf.lbnulls        = termNulls;
  521.     logBuf.lbflags        = expert | termUpper | termLF | termTab | aide;
  522.  
  523.     putLog(&logBuf, thisLog);
  524. }
  525.  
  526. /************************************************************************/
  527. /*    strCmpU() is strcmp(), but ignoring case distinctions        */
  528. /************************************************************************/
  529. int strCmpU(s, t)
  530. char s[], t[];
  531. {
  532.     char toUpper();
  533.     int  i;
  534.  
  535.     i    = 0;
  536.  
  537.     while (toUpper(s[i]) == toUpper(t[i])) {
  538.     if (s[i++] == '\0')  return 0;
  539.     }
  540.     return  toUpper(s[i]) - toUpper(t[i]);
  541. }
  542.  
  543. /************************************************************************/
  544. /*    terminate() is menu-level routine to exit system        */
  545. /************************************************************************/
  546. terminate(discon)
  547. char discon;
  548.     /* 1.  parameter <discon> is TRUE or FALSE.        */
  549.     /* 2.  if <discon> is TRUE, breaks modem connection    */
  550.     /*     or switches whichIO from CONSOLE to MODEM,    */
  551.     /*     as appropriate.                    */
  552.     /* 3.  modifies externs: struct logBuf,         */
  553.     /*             struct logTab            */
  554.     /* 4.  returns no values                */
  555.     /*          modified    dvm 9-82            */
  556. {
  557.     int i;
  558.  
  559.     if (loggedIn) {
  560.     mPrintf(" %s logged out\n ", logBuf.lbname);
  561.  
  562.     logBuf.lbgen[thisRoom]    = roomBuf.rbgen << GENSHIFT;
  563.     if (haveCarrier || onConsole)    storeLog();
  564.     loggedIn = FALSE;
  565.  
  566.     setUp(TRUE);
  567.     }
  568.  
  569.     if (discon)  {
  570.     switch (whichIO) {
  571.     case MODEM:
  572.         if (rcpm)    exitToCpm = TRUE;
  573.         else    interpret(pHangUp);
  574.  
  575.         break;
  576.     case CONSOLE:
  577.         whichIO =  MODEM;
  578.         printf("\n'MODEM' mode.\n ");
  579.         break;
  580.     }
  581.     }
  582.     for (i = 0; i < MAXROOMS; i++)    /* Clear skip bits */
  583.     roomTab[i].rtflags &= ((BYTE - 1) - SKIP);
  584. }
  585.  
  586. /************************************************************************/
  587. /*    zapLogFile() erases & re-initializes userlog.buf        */
  588. /************************************************************************/
  589. zapLogFile()
  590. {
  591.     char getCh(), toUpper();
  592.     int  i;
  593.  
  594.     printf("\nWipe out log file? ");
  595.     if (toUpper(getCh()) != 'Y')   return;
  596.  
  597.     /* clear RAM buffer out:            */
  598.     logBuf.lbvisit[0]    = ERROR;
  599.     for (i=0;  i<MAILSLOTS;  i++) {
  600.     logBuf.lbslot[i]= ERROR;
  601.     logBuf.lbId[i]    = ERROR;
  602.     }
  603.     for (i=0;  i<NAMESIZE;  i++) {
  604.     logBuf.lbname[i]= 0;
  605.     logBuf.lbpw[i]    = 0;
  606.     }
  607.  
  608.     /* write empty buffer all over file;    */
  609.     for (i=0;  i<MAXLOGTAB;  i++) {
  610.     printf("Clearing log #%d\n", i);
  611.     putLog(&logBuf, i);
  612.     }
  613. }
  614. m = TRUE;
  615.         els